#pragma once
#include<iostream>
#include<string>
#include<pthread.h>
#include<unistd.h>
#include"mutex.hpp"
#include"cond.hpp"
const int defaultcount=5;
using namespace MutexModule;
using namespace CondModule;

template<typename T>
class BlockQueue
{
private:
    bool isFull()
    {
        return _q.size()>=_cout;
    }
    bool isEmpty()
    {
        return _q.empty();
    }
public:
    BlockQueue(int count=defaultcount):
    _cout(count)
    ,csleep_num(0)
    ,psleep_num(0)
    {
    };

    void Equeue(const T& in)
    {
        LockGuard lockgard(_mutex);
        while(isFull())/*pthread_cond_wait是函数吗？有没有可能失败？pthread_cond_wait立即返回了
         pthread_cond_wait可能会因为，条件其实不满足，pthread_cond_wait 伪唤醒*/
        {
            //pthread_cond_wait调用成功，挂起当前线程，要先自动释放锁
            //被唤醒后，默认在临界区被唤醒，成功返回则需要重新申请锁
            psleep_num++;
            _full_cond.Wait(_mutex);
            psleep_num--;
        }
        _q.push(in);  
        if(csleep_num>0)
        {
            _empty_cond.Signal();
            std::cout<<"唤醒消费者..."<<std::endl;
        }
      

    }
    T pop()
    {
        LockGuard lockgard(_mutex);
        while(isEmpty())
        {
            csleep_num++;
            _empty_cond.Wait(_mutex);
            csleep_num--; 
        }
        T data=_q.front();
        _q.pop();
        if(psleep_num>0)
        {
            _full_cond.Signal();
            std::cout<<"唤醒生产者..."<<std::endl;
        }
        return data;
    }


    ~BlockQueue()
    {
       
    };

private:
    std::queue<T> _q;//临界资源
    int _cout;//容器大小

    Mutex _mutex;
    cond _full_cond;
    cond _empty_cond;

    int csleep_num;// 消费者休眠的个数
    int psleep_num;// 生产者休眠的个数
};